#include <game/flow/TriggerEntry.h>
#include <game/flow/EntryDefinition.h>
#include <game/flow/EntryExitDefinition.h>
#include <game/flow/Trigger.h>
#include <game/flow/Manager.h>
#include <game/Root.h>

#include <xml/Stream.h>
#include <system/assert.h>

ARELLO_GAME_NAMESPACE_DECL_START
namespace flow {

TriggerEntry::TriggerEntry(Manager& flowManager)
	: flowManager(flowManager)
{
}

TriggerEntry::~TriggerEntry()
{
}

bool TriggerEntry::on_attribute(xml::Provider * prov, const std::string & name, const std::string & value)
{
	if (name == "Name")
		return converter::convert(value, &this->triggerName);

	return false;
}

bool TriggerEntry::on_node(xml::Provider * prov, const std::string & name)
{
	if (name == "Exit")
	{
		std::auto_ptr<EntryExitDefinition> localExit(new EntryExitDefinition());
		if (!prov->parse_object(localExit->GetLoader()))
			return false;

		this->exits.push_back(localExit.release());
		return true;
	}

	return false;
}

Trigger* TriggerEntry::getTrigger()
{
	if (this->trigger.get())
		return this->trigger.get();

	std::auto_ptr<Trigger> localTrigger(flowManager.triggerFactory.Create(triggerName));
	if (!localTrigger.get())
	{
		LIBA_FAIL("Trigger factory failed to create trigger");
		return 0;
	}

	localTrigger->SetFlowAdjuster(this);
	localTrigger->SetServiceProvider(flowManager.root);
	this->trigger = localTrigger;
	return this->trigger.get();
}

namespace { 
bool nameIs(std::string name, EntryExitDefinition* exit)
{
	return exit->GetName() == name.c_str();
}
} // anonymous namespace

void TriggerEntry::PushFront(const std::string& exitId)
{
	std::vector<EntryExitDefinition*>::iterator i =
		std::find_if(exits.begin(),
					 exits.end(),
					 boost::bind(&nameIs, exitId, _1));

	if (i == exits.end())
	{
		LIBA_FAIL("Cannot find named exit");
		return;
	}

	std::map<std::string, EntryDefinition*>::iterator entry =
		flowManager.entries.find((*i)->GetEntry());

	if (entry == flowManager.entries.end())
	{
		LIBA_FAIL("Cannot find named entry");
		return;
	}

	flowManager.pushEntry(entry->second);
}

void TriggerEntry::ScreenChanging(EntryDefinition* newEntry)
{
	if (getTrigger())
		getTrigger()->ScreenChanging(newEntry);
}

} // namespace flow
ARELLO_GAME_NAMESPACE_DECL_END